package se480.tracker.tracker;

import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import se480.tracker.event.TrackerEvent;

/**
 * This Tracker implementation handles asynchronous requests
 * that do not expect a response.  
 * 
 * It uses a null pattern and returns a null response
 * 
 * @author mmichalak
 */
public class TrackerA implements Tracker, SynchableTracker {
	static Logger logger = Logger.getLogger(TrackerA.class.getName());
	
	/*
	 * NOTE:  the datastore is set in by the Processor
	 * as part of the processor.setTracker(Tracker) method
	 */
	Map<String, ArrayList<Location>> dataStore = null;
	
	List<TrackerEvent> partialLog = new ArrayList<TrackerEvent>();
	
	@Override
	public void saveCheckpoint() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void savePartialChanges() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public String processRequest(TrackerEvent ev) {
		logger.debug("Beginning processRequest");
		
		if (ev == null) {
			logger.error("Runtime Error - event is null?????????? ");
			return null;
		}
		
		String id = ev.getId();
		// locs = tracking history; contains each position
		ArrayList<Location> locs = dataStore.get(id);
		if (locs == null)
			locs = new ArrayList<Location>();
		
		Location loc = new Location();
		loc.setTick(ev.getTick());
		loc.setxCoord(ev.getXCoord());
		loc.setyCoord(ev.getYCoord());
		
		locs.add(loc); // put on history obj
		dataStore.put(ev.getId(), locs); // put back in map
		
		partialLog.add(ev);
		
		logger.debug("Loc map size: " + dataStore.size());
		return null;
	}
	
	/*
	 * This clears the list of last events and updates
	 * the secondary datastore.  
	 */
	public void synchPartialCheckpoint(Tracker aBak) {
		logger.debug("Beginning synchPartialCheckpoint");
		
		/*
		 * NOTE:  this step would occasionally result in ConcurrExceptions due to 
		 * existing UPDATE threads still modifying the partialLog list.  This while just
		 * catches the exception and re-tries the list access
		 */
		while (true) {
			try {
				
				for (TrackerEvent ev : partialLog) {
					aBak.processRequest(ev);
				}
				
			} catch (ConcurrentModificationException e) {
				logger.debug("Partial Log ConcurrentModification !!!!!");
			}
			break; // If gets here, finished with list and no further ConcurrExceptions
		}
		partialLog =  new ArrayList<TrackerEvent>(); // Start a new partial log
	}

	@Override
	public void setDataStore(Map<String, ArrayList<Location>> dataStore) {
		this.dataStore = dataStore;
	}

	@Override
	public Map<String, ArrayList<Location>> getDataStore() {
		return dataStore;
	}
	

}
